<!--
 * AZ翻译插件 - 翻译组件
 * @author huangguohui2002
 * @description 网页文本选择和翻译的核心交互组件
-->

<template>
  <div class="selectBox" :style="{ left: `${position.x}px`, top: `${position.y}px` }" v-show="showPopover">
    <van-popover v-model:show="showPopover" :actions="actions" :placement="currentPlacement" @open="handlePopoverOpen"
      @select="onSelect">
      <template #reference>
        <div class="popover-trigger"></div>
      </template>
    </van-popover>
  </div>

  <div class="selectBox" :style="{ left: `${position.x}px`, top: `${position.y+20}px` }" v-show="loading">
    <van-loading vertical color="#1989fa">
      <template #icon>
        <van-icon name="star-o" size="30" />
      </template>
      加载中...
    </van-loading>
  </div>

  <van-dialog v-model:show="showDialog" title="结果" width="50%">
    <p style="padding: 10%;">{{ TextResult }}</p>
  </van-dialog>


</template>

<script lang="ts" setup>
import { useTextSelection } from "@vueuse/core";//选择文本
import { useClipboard } from '@vueuse/core'//复制文本
import { ref, onMounted, onUnmounted, nextTick, onBeforeMount } from "vue";
import { browser } from 'wxt/browser'; // 导入browser API
import { showSuccessToast, showFailToast } from 'vant';

const { rects, text } = useTextSelection();
const { isSupported, copy, copied } = useClipboard()

const showPopover = ref(false);
const position = ref({ x: 0, y: 0 });
const currentPlacement = ref("bottom"); // 默认位置
const selectedText = ref("");
const apiConfig = ref<string | null>(null); // 存储API配置
const showDialog = ref(false)
const loading = ref(false);

const TextResult = ref("");

// 在组件挂载前获取缓存
onBeforeMount(async () => {
  try {
    // 获取local:api缓存
    const result: any = await storage.getItem('local:api');
    apiConfig.value = result;
  } catch (error) {
    console.error('获取缓存失败:', error);
    apiConfig.value = null;
  }
});

const actions = [
  { text: "翻译", icon: "add-o", type: "Translate" },
  { text: "复制", icon: "music-o", type: "Copy" },
  { text: "解释", icon: "more-o", type: "Explain" },
];

// 检测边界并调整位置
const adjustPlacement = () => {
  const popoverWidth = 120;
  const popoverHeight = 100;
  const viewportWidth = window.innerWidth;
  const viewportHeight = window.innerHeight;
  const { x, y } = position.value;

  const isOutOfTop = y - popoverHeight < 0;
  const isOutOfBottom = y + popoverHeight > viewportHeight;
  const isOutOfLeft = x - popoverWidth / 2 < 0;
  const isOutOfRight = x + popoverWidth / 2 > viewportWidth;

  if (currentPlacement.value.startsWith("top") && isOutOfTop) {
    currentPlacement.value = currentPlacement.value.replace("top", "bottom");
  } else if (currentPlacement.value.startsWith("bottom") && isOutOfBottom) {
    currentPlacement.value = currentPlacement.value.replace("bottom", "top");
  } else if (currentPlacement.value.startsWith("left") && isOutOfLeft) {
    currentPlacement.value = currentPlacement.value.replace("left", "right");
  } else if (currentPlacement.value.startsWith("right") && isOutOfRight) {
    currentPlacement.value = currentPlacement.value.replace("right", "left");
  }

  if (currentPlacement.value.endsWith("start") && isOutOfLeft) {
    currentPlacement.value = currentPlacement.value.replace("start", "end");
  } else if (currentPlacement.value.endsWith("end") && isOutOfRight) {
    currentPlacement.value = currentPlacement.value.replace("end", "start");
  }
};

const handleMouseUp = () => {
  setTimeout(() => {
    if (text.value && rects.value.length > 0) {
      const rect = rects.value;
      selectedText.value = text.value;
      position.value = {
        x: rect[0].x + rect[0].width / 2,
        y: rect[0].y,
      };
      currentPlacement.value = "bottom";
      showPopover.value = true;
    } else {
      showPopover.value = false;
    }
  }, 10);
};

const handlePopoverOpen = async () => {
  await nextTick();
  adjustPlacement();
};

// 发送消息到background，包含选中的文本和API配置
const invokeBackgroundFunction = async (type: string) => {
  if (!selectedText.value) {
    console.error('没有选中的文本');
    showFailToast('没有选中的文本');
    return;
  }

  if (!apiConfig.value) {
    console.error('API配置不存在');
    showFailToast('API配置不存在，请先在设置中配置API');
    return;
  }

  // 解析API配置
  let parsedConfig;
  try {
    parsedConfig = typeof apiConfig.value === 'string' ?
      JSON.parse(apiConfig.value) : apiConfig.value;
  } catch (error) {
    console.error('API配置解析失败:', error);
    showFailToast('API配置格式错误');
    return;
  }

  // 确保配置中包含modelType字段，根据URL自动识别模型类型
  if (!parsedConfig.modelType && parsedConfig.apiAddress) {
    if (parsedConfig.apiAddress.includes('modelscope')) {
      parsedConfig.modelType = 'modelscope';
    } else if (parsedConfig.apiAddress.includes('iflow.cn') || parsedConfig.apiAddress.includes('apis.iflow')) {
      parsedConfig.modelType = 'iflow';
    }
  }

  try {
    // 开启加载
    loading.value = true;
    const result: any = await new Promise((resolve, reject) => {
      browser.runtime.sendMessage(
        {
          type,
          text: selectedText.value,  // 选中的文本
          apiConfig: parsedConfig  // 解析后的API配置
        },
        (response) => {
          if (browser.runtime.lastError) {
            reject(new Error(browser.runtime.lastError.message));
          } else if (response.error) {
            reject(new Error(response.error));
          } else {
            resolve(response);
          }
        }
      );
    });

    if (result.translatedText) {
      TextResult.value = result.translatedText;
    } else {
      TextResult.value = result.translatedText;
    }
    showDialog.value = true;
    loading.value = false;
  } catch (error: any) {
    console.error('调用翻译失败:', error);
    TextResult.value = error;
    showDialog.value = true;
    loading.value = false;
  }
};

const onSelect = (action: any) => {
  switch (action.type) {
    case "Translate":
      invokeBackgroundFunction('Translate');
      break;
    case "Copy":
      copy(selectedText.value);
      break;
    case "Explain":
      invokeBackgroundFunction('Explain');
      break;
    default:
      break;
  }
};

onMounted(() => {
  document.addEventListener("mouseup", handleMouseUp);
});

onUnmounted(() => {
  document.removeEventListener("mouseup", handleMouseUp);
});
</script>

<style scoped>
.selectBox {
  position: fixed;
  pointer-events: none;
  z-index: 99999;
}

.popover-trigger {
  width: 1px;
  height: 1px;
  position: fixed;
  pointer-events: auto;
  z-index: 99999;
}
</style>
